﻿using System;
using Microsoft.Xna.Framework;

namespace FlipRunner.Physics
{
    /// <summary>
    /// CartesianPoint in Meters in a 2D Cartesian plot
    /// </summary>
    public struct CartesianPoint : IEquatable<CartesianPoint>
    {
        public static readonly CartesianPoint Zero = new CartesianPoint(0, 0);

        /// <summary>
        /// Horizontal Cartesian coordinate in Meters
        /// </summary>
        public float X;

        /// <summary>
        /// Vertical Cartesian coordinate in Meters
        /// </summary>
        public float Y;

        public CartesianPoint(float x, float y) : this()
        {
            X = x;
            Y = y;
        }

        public static CartesianVector operator -(CartesianPoint pointA, CartesianPoint pointB)
        {
            return new CartesianVector(pointA.X - pointB.X, pointA.Y - pointB.Y);
        }

        public static CartesianPoint operator +(CartesianPoint coordinate, CartesianVector vector)
        {
            return new CartesianPoint(coordinate.X + vector.X, coordinate.Y + vector.Y);
        }

        public static CartesianPoint operator -(CartesianPoint coordinate, CartesianVector vector)
        {
            return new CartesianPoint(coordinate.X - vector.X, coordinate.Y - vector.Y);
        }

        public static explicit operator CartesianPoint (Point point)
        {
            return new CartesianPoint(point.X, point.Y);
        }

        public static explicit operator CartesianPoint(Vector2 point)
        {
            return new CartesianPoint(point.X, point.Y);
        }

        public static explicit operator Vector2(CartesianPoint point)
        {
            return new Vector2(point.X, point.Y);
        }

        public static bool operator ==(CartesianPoint point, CartesianPoint point2)
        {
            return point.Equals(point2);
        }

        public static bool operator !=(CartesianPoint point, CartesianPoint point2)
        {
            return !(point == point2);
        }

        public bool Equals(CartesianPoint other)
        {
            return X.Equals(other.X) && Y.Equals(other.Y);
        }

        public override bool Equals(object obj)
        {
            if (ReferenceEquals(null, obj)) return false;
            return obj is CartesianPoint && Equals((CartesianPoint) obj);
        }

        public override int GetHashCode()
        {
            unchecked
            {
                return (X.GetHashCode()*397) ^ Y.GetHashCode();
            }
        }

        public override string ToString()
        {
            return ((Vector2) this).ToString();
        }

        public Point ToPixels (float pixelsPerMeter, int totalHeight)
        {
            return new Point((int) Math.Round(pixelsPerMeter * X),totalHeight - (int) Math.Round( pixelsPerMeter * Y));
        }
    }
}